/*
	@file: log/source/detail/LogPriorityHelper.cpp
	@author: Wolfhead
 */
#include "detail/LogPriorityHelper.h"
#include <vector>
#include <sstream>
#include <boost/algorithm/string.hpp>	

namespace logger
{

LogPriority LogPriorityHelper::parse_priority(const std::string& str_priority)
{
	bool cover = false;
	if (boost::ends_with(str_priority, "+"))
	{
		cover = true;
	}

	std::string priority = 
		boost::trim_right_copy_if(str_priority, boost::is_any_of("+"));
	std::vector<std::string> token;
	boost::split(token, priority, boost::is_any_of("|"), boost::token_compress_on);

	LogPriority pri = kNone;
	for (size_t i = 0; i != token.size(); ++i)
	{
		pri |= string_to_priority(boost::trim_copy(token[i]));
	}

	if (cover)
	{
		return cover_priority(pri);
	}
	else
	{
		return pri;
	}
}

#define PRIORITY_STR_MAP(str, pri) 		\
	else if (str == #pri) {        		\
		return k##pri; 					\
	}									\

LogPriority LogPriorityHelper::string_to_priority(
	const std::string& str_priority)
{
	if (0) {}
	PRIORITY_STR_MAP(str_priority, Perf)
	PRIORITY_STR_MAP(str_priority, Debug3)
	PRIORITY_STR_MAP(str_priority, Debug2)
	PRIORITY_STR_MAP(str_priority, Debug1)
	PRIORITY_STR_MAP(str_priority, Debug)
	PRIORITY_STR_MAP(str_priority, Info)
	PRIORITY_STR_MAP(str_priority, Notice)
	PRIORITY_STR_MAP(str_priority, Warning)
	PRIORITY_STR_MAP(str_priority, Error)
	PRIORITY_STR_MAP(str_priority, None)
	PRIORITY_STR_MAP(str_priority, All)
	PRIORITY_STR_MAP(str_priority, Perf)
	else if (str_priority == "ByName")
	{
		return kName;
	}
	else
	{
		return kNone;
	}
}

std::string LogPriorityHelper::priority_to_string(LogPriority priority)
{
	switch (priority)
	{
		case kPerf : return "Perf";
		case kDebug3 : return "Debug3";	
		case kDebug2 : return "Debug2";
		case kDebug1 : return "Debug1";
		case kDebug : return "Debug";
		case kInfo : return "Info";
		case kNotice : return "Notice";
		case kWarning : return "Warning";
		case kError : return "Error";
		case kCritical : return "Critical";
		case kName : return "ByName";
		default	:
		{
			std::stringstream oss;
			oss << "PRI:" << priority;
			return oss.str();
		}
	}
}

LogPriority LogPriorityHelper::cover_priority(LogPriority priority)
{
	size_t mark = 0;

	if (priority == 0)
	{
		return 0;
	}

	for (size_t i = 0; i != kPrioritySize; ++i)
	{
		if (priority & kBase << i)
		{
			mark = i;
			break;
		}
	}

	LogPriority pri = (0 - (kBase << mark)) | (kBase << mark);
	return (pri & kSystemMask) | priority;
}

}//logger
